package com.example.ribbonconsumer.command;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import com.example.ribbonconsumer.model.User;
import com.example.ribbonconsumer.service.UserService;
import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCollapserProperties;
import com.netflix.hystrix.HystrixCommand;

/**
 * 请求合并器
 * @author c_dingxuehua-001
 *
 */
public class UserCollapseCommand extends HystrixCollapser<List<User>,User,Long>{
	
	private UserService userService;
	
	private Long userId;
	
	public UserCollapseCommand(UserService userService, Long userId) {
		//设置了时间延迟属性，合并器会在该时间窗内收集获取单个User的请求并在时间窗结束时进行合并
		//组装成单个批量请求
		super(Setter.withCollapserKey(HystrixCollapserKey.Factory.asKey("userCollapseCommand"))
				.andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter()
						.withTimerDelayInMilliseconds(100)));
		this.userService = userService;
		this.userId = userId;
	}

	/**
	 * 合并请求产生批量命令的具体方法
	 */
	@Override
	protected HystrixCommand<List<User>> createCommand(
			Collection<com.netflix.hystrix.HystrixCollapser.CollapsedRequest<User, Long>> collapsedRequests) {
			List<Long> userIds = new ArrayList<>(collapsedRequests.size());
			userIds.addAll(collapsedRequests.stream().map(CollapsedRequest::getArgument).collect(Collectors.toList()));
		return new UserBatchCommand(userService, userIds);
	}

	/**
	 * 获取请求参数
	 */
	@Override
	public Long getRequestArgument() {
		return userId;
	}

	/**
	 * 批量命令结果返回后的处理，这里需要实现将批量结果拆分并传递给合并前的各个原子请求命令的逻辑
	 */
	@Override
	protected void mapResponseToRequests(List<User> batchResponse,
			Collection<com.netflix.hystrix.HystrixCollapser.CollapsedRequest<User, Long>> collapsedRequests) {
		int count = 0;
		for(CollapsedRequest<User, Long> collapsedRequest : collapsedRequests){
			User user = batchResponse.get(count ++);
			collapsedRequest.setResponse(user);
		}
	}

}
